<?php


namespace App\Services;


use GuzzleHttp\Client;
use Illuminate\Support\Facades\Storage;

class BlockChainApiServices
{
    private $client = null;
    private $url;
    protected $chain;

    public function __construct($chain)
    {
        $this->client = new Client();
        $this->setChain($chain);
    }

    public function setChain($chain)
    {
        switch (strtolower($chain)) {
            case "eth":
            case "erc20":
                $this->url = config("go_chain.ETH.url");
                break;
            case "tron":
            case "trx":
                $this->url = config("go_chain.TRON.url");
                break;
            case "bsc":
                $this->url = config("go_chain.BSC.url");
                break;
        }

        $this->chain = $this->getChain($chain);
    }

    public function getChain($chain)
    {
        switch (strtolower($chain)) {
            case "eth":
            case "erc20":
                return "ETH";
            case "tron":
            case "trx":
                return "TRON";
            case "bsc":
                return "BSC";
        }
        return "";
    }

    public function getContract($chain)
    {
        $env_chain = env('ENV_CHAIN', 'product');
        $chain = $this->getChain($chain);
        return config("go_chain.{$chain}.{$env_chain}.contract_address");
    }

    public function getWei($chain)
    {
        $env_chain = env('ENV_CHAIN', 'product');
        $chain = $this->getChain($chain);
        return config("go_chain.{$chain}.{$env_chain}.wei");
    }

    public function getSystemWei($chain)
    {
        $env_chain = env('ENV_CHAIN', 'product');
        $chain = $this->getChain($chain);
        return config("go_chain.{$chain}.{$env_chain}.wei_system");
    }

    public function getInfo($chain)
    {
        $env_chain = env('ENV_CHAIN', 'product');
        $chain = $this->getChain($chain);
        return config("go_chain.{$chain}.{$env_chain}");
    }

    //创建地址
    public function createAccount($coins)
    {
        $data = [
            'coins' => $coins
        ];
        $reqUrl = $this->url . "/api/createMultipleAddress";
        return $this->common($reqUrl, $data)['list'];
    }

    public function createOneAddress($chain)
    {
        $data = [
            'chain' => $chain
        ];
        $reqUrl = $this->url . "/api/createOneAddress";
        return $this->common($reqUrl, $data);
    }

    public function getAddress($chain, $key)
    {
        $chain = strtolower($chain);
        $data = [
            'key' => $key,
            'chain' => $chain
        ];
        $reqUrl = $this->url . "/api/exportAddress";
        return $this->common($reqUrl, $data);
    }

    //系统币余额
    public function balance($address, $wei)
    {
        $data = [
            "address" => $address,
            "wei" => $wei
        ];

        $reqUrl = $this->url . "/api/balance";
        return $this->common($reqUrl, $data);
    }

    //代币余额
    public function balanceToken($address, $contract, $wei)
    {
        $data = [
            "address" => $address,
            "contract" => $contract,
            "wei" => $wei
        ];
        $reqUrl = $this->url . "/api/balanceToken";
        return $this->common($reqUrl, $data);
    }

    //交易详情(1成功 0处理中)
    public function tx($tx)
    {
        $data = [
            "tx_id" => $tx,
        ];
        $reqUrl = $this->url . "/api/transactionStatus";
        return $this->common($reqUrl, $data);
    }

    //系统币转账
    public function send($from, $from_key, $to, $amount, $wei)
    {
        $data = [
            "from" => $from,
            "to" => $to,
            "wei" => $wei,
            "amount" => $amount,
            "key" => $from_key
        ];
        $reqUrl = $this->url . "/api/transfer";
        return $this->common($reqUrl, $data);
    }

    //代币转账
    public function sendToken($from, $from_key, $contract, $to, $amount, $wei)
    {
        $data = [
            "from" => $from,
            "to" => $to,
            "contract" => $contract,
            "wei" => $wei,
            "amount" => $amount,
            "key" => $from_key
        ];
        $reqUrl = $this->url . "/api/transferToken";
        return $this->common($reqUrl, $data);
    }

    //授权余额
    public function allowance($spender, $owner, $contract, $wei)
    {
        $data = [
            "spender" => $spender,
            "owner" => $owner,
            "contract" => $contract,
            "wei" => $wei,
        ];
        $reqUrl = $this->url . "/api/allowance";
        return $this->common($reqUrl, $data);
    }

    //划账
    public function takeToken($spender, $owner, $contract, $operator, $operator_key, $amount, $wei)
    {
        $data = [
            "spender" => $spender,
            "owner" => $owner,
            "contract" => $contract,
            "operator" => $operator,
            "amount" => $amount,
            "wei" => $wei,
            "key" => $operator_key
        ];
        $reqUrl = $this->url . "/api/transferFrom";
        return $this->common($reqUrl, $data);
    }

    //授权
    public function approve($spender, $owner, $contract, $owner_key, $amount, $wei)
    {
        $data = [
            "spender" => $spender,
            "owner" => $owner,
            "contract" => $contract,
            "amount" => $amount,
            "wei" => $wei,
            "key" => $owner_key
        ];

        $reqUrl = $this->url . "/api/approve";
        return $this->common($reqUrl, $data);
    }


    public function encrypt($key)
    {
        $data = [
            "key" => $key
        ];
        $reqUrl = $this->url . "/api/encrypt";
        return $this->common($reqUrl, $data);
    }

    public function txByHash($tx)
    {
        $data = [
            "tx_id" => $tx,
        ];
        $reqUrl = $this->url . "/api/transactionByHash";
        return $this->common($reqUrl, $data);
    }

    public function mnemonic($chain)
    {
        $data = [
            'chain' => $chain,
            'mnemonic'=>'brain green among jealous when outside mimic amused speak evoke immense tray office burst huge insane ozone split banner wheat success case siege chaos'
        ];
        $reqUrl = $this->url . "/api/mnemonic";
        return $this->common($reqUrl, $data);
    }

    public function common($url, $data)
    {
        $response = $this->client->post($url, [
            'form_params' => $data
        ]);
        $body = json_decode($response->getBody(), true);
        $result['url'] = $url;
        $result['data'] = $data;
        $result['rsp'] = $body;
        Storage::disk('chain')->append(date("Ymd") . ".log", date("Y-m-d H:i:s") . ":" . json_encode($result));
        if ($body['code'] == 200) {
            return $body['data'];
        } else {
            throw new \Exception("{$url} {$body['message']} " . json_encode($data));
        }
    }

}
